//************************************************************************
// author	:	vera												
// date		:	2011/4/7 0:02 					                 
//************************************************************************
#ifndef SL_VECTOR_H_
#define SL_VECTOR_H_
#include "Config.h"
#include <Math.h>
namespace sl
{
	class SL_EXPORT Vector3
	{
		public:

			typedef float value_type;

			Vector3(void) { _v[0] = 0.0f; _v[1] = 0.0f; _v[2] = 0.0f; };
			Vector3( value_type x, value_type y, value_type z ) { _v[0] = x; _v[1] = y; _v[2] = z;  };
			Vector3( const Vector3 & v ) { _v[0] = v._v[0]; _v[1] = v._v[1]; _v[2] = v._v[2]; }
			~Vector3(void) {};

			value_type  _v[3];

			inline bool operator == ( const Vector3 & v ) const  { return _v[0] == v._v[0] && _v[1] == v._v[1] && _v[2] == v._v[2]; }
			inline bool operator != ( const Vector3 & v ) const { return _v[0] != v._v[0] || _v[1] != v._v[1] || _v[2] != v._v[2]; }

			inline Vector3 & operator = (const Vector3 & v )	{ _v[0] = v._v[0]; _v[1] = v._v[1]; _v[2] = v._v[2]; return *this; }
			inline Vector3  operator + (const Vector3 & v )	const { return Vector3( _v[0] + v._v[0], _v[1] + v._v[1], _v[2] + v._v[2] );}
			inline Vector3 & operator += (const Vector3 & v )	{ _v[0] += v._v[0]; _v[1] += v._v[1]; _v[2] += v._v[2]; return *this; }
			inline Vector3  operator - (const Vector3 & v )	const { return Vector3( _v[0] - v._v[0], _v[1] - v._v[1], _v[2] - v._v[2]); }
			inline Vector3 & operator -= (const Vector3 & v )	{ _v[0] -= v._v[0]; _v[1] -= v._v[1]; _v[2] -= v._v[2]; return *this; }
			
			inline value_type  operator * ( const Vector3 & v )	{ return (_v[0] * v._v[0] + _v[1] * v._v[1] +  _v[2] * v._v[2]); }

			inline Vector3  operator ^ ( const Vector3 & v ) const 
			{
				return Vector3(_v[1]*v._v[2]-_v[2]*v._v[1],
								_v[2]*v._v[0]-_v[0]*v._v[2] ,
								_v[0]*v._v[1]-_v[1]*v._v[0]);
			}

			inline Vector3  operator * ( const value_type rhs )
			{
				return Vector3( _v[0] * rhs, _v[1] * rhs, _v[2] * rhs ); 
			}

			inline Vector3 & operator *= ( const value_type rhs )
			{
				_v[0] *= rhs;
				_v[1] *= rhs;
				_v[2] *= rhs;
				return *this;
			}

			inline Vector3 operator /= ( const value_type rhs )
			{
				_v[0] /= rhs;
				_v[1] /= rhs;
				_v[2] /= rhs;
				return *this;
			}

			inline Vector3 operator / ( const value_type rhs )
			{
				return Vector3( _v[0]/rhs, _v[1]/rhs, _v[2]/rhs );
			}

			inline const Vector3  operator - () const 
			{
				return Vector3( -_v[0], -_v[1], -_v[2] );
			}

			inline value_type& operator [] (u32 i) { return _v[i]; }
			inline value_type operator [] (u32 i) const { return _v[i]; }

			inline value_type& x() { return _v[0]; }
			inline value_type& y() { return _v[1]; }
			inline value_type& z() { return _v[2]; }

			inline value_type x() const { return _v[0]; }
			inline value_type y() const { return _v[1]; }
			inline value_type z() const { return _v[2]; }


			// calculate sqrt vec * vec
			inline value_type length() const 
			{
				return sqrt( _v[0]*_v[0]  + _v[1] * _v[1] + _v[2] * _v[2] );
			}

			// calculate the vec * vec 
			inline value_type length2() const 
			{
				return ( _v[0]*_v[0]  + _v[1] * _v[1] + _v[2] * _v[2] );
			}

			inline value_type normalize()
			{
				value_type norm = Vector3::length();
				if ( norm > 0.0 )
				{
					value_type inv = 1/norm;
					_v[0] *= inv;
					_v[1] *= inv;
					_v[2] *= inv;
				}
				return norm;
			}

			static 	const Vector3	X_AXIS;
			static	const Vector3	Y_AXIS;
			static	const Vector3	Z_AXIS;


	};
}


#endif
